home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume27 / dmake / part02 < prev    next >
Encoding:
Text File  |  1992-01-29  |  40.0 KB  |  1,412 lines

  1. Newsgroups: comp.sources.misc
  2. From: dvadura@plg.waterloo.edu (Dennis Vadura)
  3. Subject:  v27i103:  dmake - dmake Version 3.8, Part02/41
  4. Message-ID: <1992Jan28.030922.6601@sparky.imd.sterling.com>
  5. X-Md4-Signature: 15cfefd47434392118a0f0e6ec31c1ce
  6. Date: Tue, 28 Jan 1992 03:09:22 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: dvadura@plg.waterloo.edu (Dennis Vadura)
  10. Posting-number: Volume 27, Issue 103
  11. Archive-name: dmake/part02
  12. Environment: Atari-ST, Coherent, Mac, MSDOS, OS/2, UNIX
  13. Supersedes: dmake: Volume 19, Issue 22-58
  14.  
  15. ---- Cut Here and feed the following to sh ----
  16. # this is dmake.shar.02 (part 2 of a multipart archive)
  17. # do not concatenate these parts, unpack them in order with /bin/sh
  18. # file dmake/dag.c continued
  19. #
  20. if test ! -r _shar_seq_.tmp; then
  21.     echo 'Please unpack part 1 first!'
  22.     exit 1
  23. fi
  24. (read Scheck
  25.  if test "$Scheck" != 2; then
  26.     echo Please unpack part "$Scheck" next!
  27.     exit 1
  28.  else
  29.     exit 0
  30.  fi
  31. ) < _shar_seq_.tmp || exit 1
  32. if test -f _shar_wnt_.tmp; then
  33. sed 's/^X//' << 'SHAR_EOF' >> 'dmake/dag.c' &&
  34. X   }
  35. X   else    {    /* search the list, checking for duplicates    */
  36. X      for( lp = cell->ce_prq;
  37. X       (lp->cl_next != NIL(LINK)) && (lp->cl_prq != prq);
  38. X       lp = lp->cl_next );
  39. X
  40. X      /* If the prq is not found and we are at the last prq in the list,
  41. X       * allocate a new prq and place it into the list, insert it at the
  42. X       * head if head == 1, else we add it to the end. */
  43. X
  44. X      if( lp->cl_prq != prq ) {
  45. X     TALLOC( tlp, 1, LINK );
  46. X     tlp->cl_prq = prq;
  47. X
  48. X     if( head ) {
  49. X        tlp->cl_next = cell->ce_prq;
  50. X        cell->ce_prq = tlp;
  51. X     }
  52. X     else
  53. X        lp->cl_next  = tlp;
  54. X
  55. X     lp = tlp;
  56. X      }
  57. X   }
  58. X
  59. X   DB_RETURN( lp );
  60. }
  61. X
  62. X
  63. X
  64. PUBLIC void
  65. Clear_prerequisites( cell )/*
  66. =============================
  67. X    Clear out the list of prerequisites, freeing all of the LINK nodes,
  68. X    and setting the list to NULL */
  69. CELLPTR cell;
  70. {
  71. X   LINKPTR lp, tlp;
  72. X
  73. X   DB_ENTER( "Clear_prerequisites" );
  74. X   DB_PRINT( "cell", ("Nuking prerequisites") );
  75. X
  76. X   if( cell == NIL(CELL) ) { DB_VOID_RETURN; }
  77. X
  78. X   for( lp=cell->ce_prq; lp != NIL(LINK); lp=tlp ) {
  79. X      tlp=lp->cl_next;
  80. X      FREE( lp );
  81. X   }
  82. X
  83. X   cell->ce_prq = NIL(LINK);
  84. X
  85. X   DB_VOID_RETURN;
  86. }
  87. X
  88. X
  89. PUBLIC int
  90. Test_circle( cp, fail )/*
  91. =========================
  92. X    Actually run through the graph */
  93. CELLPTR cp;
  94. int     fail;
  95. {
  96. X   register LINKPTR lp;
  97. X   int res = 0;
  98. X
  99. X   DB_ENTER( "Test_circle" );
  100. X   DB_PRINT( "tc", ("checking [%s]", cp->CE_NAME) );
  101. X
  102. X   if( cp->ce_flag & F_MARK )
  103. X      if( fail )
  104. X     Fatal("Detected circular dependency in graph at [%s]", cp->CE_NAME);
  105. X      else
  106. X     DB_RETURN( 1 );
  107. X
  108. X   cp->ce_flag |= F_MARK;
  109. X   for( lp = cp->ce_prq; !res && lp != NIL(LINK); lp = lp->cl_next )
  110. X      res = Test_circle( lp->cl_prq, fail );
  111. X   cp->ce_flag ^= F_MARK;
  112. X
  113. X   DB_RETURN( res );
  114. }
  115. X
  116. X
  117. X
  118. PUBLIC STRINGPTR
  119. Def_recipe( rcp, sp, white_too, no_check )/*
  120. =============================================
  121. X    Take the recipe and add it to the list of recipes
  122. X    pointed to by sp.  sp points to the last element.
  123. X    return a pointer to the new recipe.  If white_too == TRUE add the
  124. X    recipe even if it contains only white space.
  125. X    If no_check is true then don't look for -@ at the start of the
  126. X    recipe line. */
  127. char      *rcp;
  128. STRINGPTR sp;
  129. int       white_too;
  130. int       no_check;
  131. {
  132. X   register STRINGPTR nsp;
  133. X   register char      *rp;
  134. X
  135. X   DB_ENTER( "Def_recipe" );
  136. X   DB_PRINT( "rul", ("Defining recipe %s", rcp) );
  137. X
  138. X   if( !white_too ) rcp = _strspn( rcp, " \t" );
  139. X   if( (rcp == NIL(char)) || (*rcp == 0 && !white_too) )
  140. X      DB_RETURN( sp );         /* return last recipe when new recipe not added */
  141. X
  142. X   rp = no_check ? rcp : _strspn( rcp, " \t@-+%" );
  143. X
  144. X   TALLOC( nsp, 1, STRING );
  145. X   nsp->st_string = _strdup( rp );
  146. X
  147. X   if( sp != NIL(STRING) ) sp->st_next = nsp;
  148. X   nsp->st_next = NIL(STRING);
  149. X
  150. X   if( !no_check ) nsp->st_attr |= Rcp_attribute( rcp );
  151. X
  152. X   DB_RETURN( nsp );
  153. }
  154. X
  155. X
  156. PUBLIC t_attr
  157. Rcp_attribute( rp )/*
  158. ======================
  159. X   Look at the recipe and return the set of attributes that it defines. */
  160. char *rp;
  161. {
  162. X   t_attr flag = A_DEFAULT;
  163. X   int    done = FALSE;
  164. X
  165. X   while( !done )
  166. X      switch( *rp++ )
  167. X      {
  168. X     case '@' : flag |= A_SILENT; break;
  169. X     case '-' : flag |= A_IGNORE; break;
  170. X     case '+' : flag |= A_SHELL;  break;
  171. X     case '%' : flag |= A_SWAP;   break;
  172. X
  173. X     case ' ' :
  174. X     case '\t': break;
  175. X
  176. X     default: done = TRUE; break;
  177. X      }
  178. X
  179. X   return(flag);
  180. }
  181. SHAR_EOF
  182. chmod 0640 dmake/dag.c ||
  183. echo 'restore of dmake/dag.c failed'
  184. Wc_c="`wc -c < 'dmake/dag.c'`"
  185. test 14085 -eq "$Wc_c" ||
  186.     echo 'dmake/dag.c: original size 14085, current size' "$Wc_c"
  187. rm -f _shar_wnt_.tmp
  188. fi
  189. # ============= dmake/db.h ==============
  190. if test -f 'dmake/db.h' -a X"$1" != X"-c"; then
  191.     echo 'x - skipping dmake/db.h (File already exists)'
  192.     rm -f _shar_wnt_.tmp
  193. else
  194. > _shar_wnt_.tmp
  195. sed 's/^X//' << 'SHAR_EOF' > 'dmake/db.h' &&
  196. /* RCS      -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/db.h,v 1.1 1992/01/24 03:29:35 dvadura Exp $
  197. -- SYNOPSIS -- front end to DBUG macros.
  198. -- 
  199. -- DESCRIPTION
  200. --    This is a front end to Fred Fish's DBUG macros.  The intent was
  201. --    to provide an interface so that if you don't have the DBUG code
  202. --    you can still compile dmake, by undefining DBUG, if you do have
  203. --    the code then you can use Fred Fish's DBUG package.  Originally
  204. --    the DBUG stuff was copyrighted, it is now in the public domain
  205. --    so the need for this is not as apparent.
  206. -- 
  207. -- AUTHOR
  208. --      Dennis Vadura, dvadura@watdragon.uwaterloo.ca
  209. --      CS DEPT, University of Waterloo, Waterloo, Ont., Canada
  210. --
  211. -- COPYRIGHT
  212. --      Copyright (c) 1990 by Dennis Vadura.  All rights reserved.
  213. -- 
  214. --      This program is free software; you can redistribute it and/or
  215. --      modify it under the terms of the GNU General Public License
  216. --      (version 1), as published by the Free Software Foundation, and
  217. --      found in the file 'LICENSE' included with this distribution.
  218. -- 
  219. --      This program is distributed in the hope that it will be useful,
  220. --      but WITHOUT ANY WARRANTY; without even the implied warrant of
  221. --      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  222. --      GNU General Public License for more details.
  223. -- 
  224. --      You should have received a copy of the GNU General Public License
  225. --      along with this program;  if not, write to the Free Software
  226. --      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  227. --
  228. -- LOG
  229. --     $Log: db.h,v $
  230. X * Revision 1.1  1992/01/24  03:29:35  dvadura
  231. X * dmake Version 3.8, Initial revision
  232. X *
  233. */
  234. X
  235. #ifndef    DB_h
  236. #define    DB_h
  237. X
  238. #ifdef DBUG
  239. X
  240. #  include "dbug.h"
  241. X
  242. #  define DB_ENTER(a1)                DBUG_ENTER(a1)
  243. #  define DB_RETURN(a1)               DBUG_RETURN(a1)
  244. #  define DB_VOID_RETURN              DBUG_VOID_RETURN
  245. #  define DB_EXECUTE(keyword, a1)     DBUG_EXECUTE(keyword,a1)
  246. #  define DB_PRINT(keyword,arglist)   DBUG_PRINT(keyword,arglist)
  247. #  define DB_PUSH(a1)                 DBUG_PUSH(a1)
  248. #  define DB_POP()                    DBUG_POP()
  249. #  define DB_PROCESS(a1)              DBUG_PROCESS(a1)
  250. #  define DB_FILE(file)               DBUG_FILE(file)
  251. #  define DB_SETJMP                   DBUG_SETJMP
  252. #  define DB_LONGJMP                  DBUG_LONGJMP
  253. X
  254. #else
  255. X
  256. #  define DB_ENTER(a1)
  257. #  define DB_RETURN(a1)               return (a1)
  258. #  define DB_VOID_RETURN              return
  259. #  define DB_EXECUTE(keyword, a1)
  260. #  define DB_PRINT(keyword,arglist)
  261. #  define DB_PUSH(a1)
  262. #  define DB_POP()
  263. #  define DB_PROCESS(a1)
  264. #  define DB_FILE(file)
  265. #  define DB_SETJMP                   setjmp
  266. #  define DB_LONGJMP                  longjmp
  267. X
  268. #endif
  269. #endif
  270. X
  271. SHAR_EOF
  272. chmod 0640 dmake/db.h ||
  273. echo 'restore of dmake/db.h failed'
  274. Wc_c="`wc -c < 'dmake/db.h'`"
  275. test 2705 -eq "$Wc_c" ||
  276.     echo 'dmake/db.h: original size 2705, current size' "$Wc_c"
  277. rm -f _shar_wnt_.tmp
  278. fi
  279. # ============= dmake/dbug/README ==============
  280. if test ! -d 'dmake/dbug'; then
  281.     mkdir 'dmake/dbug'
  282. fi
  283. if test -f 'dmake/dbug/README' -a X"$1" != X"-c"; then
  284.     echo 'x - skipping dmake/dbug/README (File already exists)'
  285.     rm -f _shar_wnt_.tmp
  286. else
  287. > _shar_wnt_.tmp
  288. sed 's/^X//' << 'SHAR_EOF' > 'dmake/dbug/README' &&
  289. This directory contains two public domain debugging packages.
  290. X
  291. X    1. Fred Fishes DEBUG macros.
  292. X    2. Connor P. Cahills malloc library.
  293. X
  294. Descriptions of both can be found in their respective sub-directories.  dbug
  295. for the DEBUG macros and malloc for the malloc library.  I have left the
  296. malloc distribution intact as it comes from the net except for the changes
  297. noted in the _changes file.
  298. X
  299. I thank the authors for making them available for others to use.
  300. X
  301. -dennis
  302. SHAR_EOF
  303. chmod 0640 dmake/dbug/README ||
  304. echo 'restore of dmake/dbug/README failed'
  305. Wc_c="`wc -c < 'dmake/dbug/README'`"
  306. test 460 -eq "$Wc_c" ||
  307.     echo 'dmake/dbug/README: original size 460, current size' "$Wc_c"
  308. rm -f _shar_wnt_.tmp
  309. fi
  310. # ============= dmake/dbug/dbug.mk ==============
  311. if test -f 'dmake/dbug/dbug.mk' -a X"$1" != X"-c"; then
  312.     echo 'x - skipping dmake/dbug/dbug.mk (File already exists)'
  313.     rm -f _shar_wnt_.tmp
  314. else
  315. > _shar_wnt_.tmp
  316. sed 's/^X//' << 'SHAR_EOF' > 'dmake/dbug/dbug.mk' &&
  317. # Set the proper macros based on whether we are making the debugging version
  318. # or not.  The valid parameters to this file are:
  319. #
  320. #    DEBUG=1        ==> enable the making of the DBUG version
  321. #    DBMALLOC=1    ==> enable DBUG version with extensive MALLOC checking
  322. #
  323. #    DB_CFLAGS    ==> CFLAGS is set to this value at the end if DEBUG=1
  324. #    DB_LDFLAGS    ==> LDFLAGS is set to this at the end if DEBUG=1
  325. #    DB_LDLIBS       ==> LDLIBS is set to this at end if DEBUG=1
  326. #
  327. # The non debug versions of the above three macros are:
  328. #
  329. #    NDB_CFLAGS
  330. #    NDB_LDFLAGS
  331. #    NDB_LDLIBS
  332. #
  333. # One of the set of three should have values set appropriately prior to
  334. # sourcing this file.
  335. X
  336. .IF $(DEBUG)
  337. X   DBUG_SRC    += dbug.c
  338. X   DB_CFLAGS    += -Idbug/dbug
  339. X
  340. X   .SETDIR=dbug/dbug : $(DBUG_SRC)
  341. X
  342. X   # If DBMALLOC is requested (ie non-NULL) then include the sources for
  343. X   # compilation.  BSD 4.3 needs the getwd.c source compiled in due to a bug
  344. X   # in the clib getwd routine.
  345. X   .IF $(DBMALLOC)
  346. X      # Serious bug in bsd43 getwd.c would free a string and then use its
  347. X      # value.  The DBMALLOC code clears a string when it is free'd so the
  348. X      # value was no longer valid and the returned path for the current
  349. X      # directory was now completely wrong.
  350. X      .IF $(OSRELEASE) == bsd43
  351. X     GETWD_SRC += getwd.c
  352. X     .SETDIR=dbug : $(GETWD_SRC)
  353. X      .END
  354. X
  355. X      MLC_SRC   += malloc.c free.c realloc.c calloc.c string.c\
  356. X           mlc_chk.c mlc_chn.c memory.c tostring.c m_perror.c\
  357. X           m_init.c mallopt.c dump.c
  358. X
  359. X      .SETDIR=dbug/malloc : $(MLC_SRC)
  360. X
  361. X      DB_CFLAGS += -Idbug/malloc
  362. X   .END
  363. X
  364. X   SRC          += $(DBUG_SRC) $(MLC_SRC) $(GETWD_SRC)
  365. X   HDR        += db.h 
  366. X
  367. X   LDFLAGS    += $(DB_LDFLAGS)
  368. X   LDLIBS    += $(DB_LDLIBS)
  369. X
  370. X   SILENT    := $(.SILENT)
  371. X   .SILENT    := yes
  372. X   TARGET    := db$(TARGET)
  373. X   OBJDIR    := $(OBJDIR).dbg
  374. X   .SILENT    := $(SILENT)
  375. X
  376. X   CFLAGS    += $(DB_CFLAGS)
  377. X   .KEEP_STATE  := _dbstate.mk
  378. .ELSE
  379. X   CFLAGS       += $(NDB_CFLAGS)
  380. X   LDFLAGS      += $(NDB_LDFLAGS)
  381. X   LDLIBS       += $(NDB_LDLIBS)
  382. .END
  383. SHAR_EOF
  384. chmod 0640 dmake/dbug/dbug.mk ||
  385. echo 'restore of dmake/dbug/dbug.mk failed'
  386. Wc_c="`wc -c < 'dmake/dbug/dbug.mk'`"
  387. test 1955 -eq "$Wc_c" ||
  388.     echo 'dmake/dbug/dbug.mk: original size 1955, current size' "$Wc_c"
  389. rm -f _shar_wnt_.tmp
  390. fi
  391. # ============= dmake/dbug/dbug/README ==============
  392. if test ! -d 'dmake/dbug/dbug'; then
  393.     mkdir 'dmake/dbug/dbug'
  394. fi
  395. if test -f 'dmake/dbug/dbug/README' -a X"$1" != X"-c"; then
  396.     echo 'x - skipping dmake/dbug/dbug/README (File already exists)'
  397.     rm -f _shar_wnt_.tmp
  398. else
  399. > _shar_wnt_.tmp
  400. sed 's/^X//' << 'SHAR_EOF' > 'dmake/dbug/dbug/README' &&
  401. To unpack the DBUG manual page please issue the following sequence of
  402. commands:
  403. X
  404. X    uudecode dbug.uue
  405. X    uncompress dbug.Z
  406. X    mv dbug dbug.p
  407. SHAR_EOF
  408. chmod 0640 dmake/dbug/dbug/README ||
  409. echo 'restore of dmake/dbug/dbug/README failed'
  410. Wc_c="`wc -c < 'dmake/dbug/dbug/README'`"
  411. test 135 -eq "$Wc_c" ||
  412.     echo 'dmake/dbug/dbug/README: original size 135, current size' "$Wc_c"
  413. rm -f _shar_wnt_.tmp
  414. fi
  415. # ============= dmake/dbug/dbug/dbug.c ==============
  416. if test -f 'dmake/dbug/dbug/dbug.c' -a X"$1" != X"-c"; then
  417.     echo 'x - skipping dmake/dbug/dbug/dbug.c (File already exists)'
  418.     rm -f _shar_wnt_.tmp
  419. else
  420. > _shar_wnt_.tmp
  421. sed 's/^X//' << 'SHAR_EOF' > 'dmake/dbug/dbug/dbug.c' &&
  422. /******************************************************************************
  423. X *                                          *
  424. X *                               N O T I C E                      *
  425. X *                                          *
  426. X *                  Copyright Abandoned, 1987, Fred Fish              *
  427. X *                                          *
  428. X *                                          *
  429. X *    This previously copyrighted work has been placed into the  public     *
  430. X *    domain  by  the  author  and  may be freely used for any purpose,     *
  431. X *    private or commercial.                              *
  432. X *                                          *
  433. X *    Because of the number of inquiries I was receiving about the  use     *
  434. X *    of this product in commercially developed works I have decided to     *
  435. X *    simply make it public domain to further its unrestricted use.   I     *
  436. X *    specifically  would  be  most happy to see this material become a     *
  437. X *    part of the standard Unix distributions by AT&T and the  Berkeley     *
  438. X *    Computer  Science  Research Group, and a standard part of the GNU     *
  439. X *    system from the Free Software Foundation.                  *
  440. X *                                          *
  441. X *    I would appreciate it, as a courtesy, if this notice is  left  in     *
  442. X *    all copies and derivative works.  Thank you.                  *
  443. X *                                          *
  444. X *    The author makes no warranty of any kind  with  respect  to  this     *
  445. X *    product  and  explicitly disclaims any implied warranties of mer-     *
  446. X *    chantability or fitness for any particular purpose.              *
  447. X *                                          *
  448. X ******************************************************************************
  449. X */
  450. X
  451. X
  452. /*
  453. X *  FILE
  454. X *
  455. X *    dbug.c   runtime support routines for dbug package
  456. X *
  457. X *  SCCS
  458. X *
  459. X *    @(#)dbug.c    1.19 9/5/87
  460. X *
  461. X *  DESCRIPTION
  462. X *
  463. X *    These are the runtime support routines for the dbug package.
  464. X *    The dbug package has two main components; the user include
  465. X *    file containing various macro definitions, and the runtime
  466. X *    support routines which are called from the macro expansions.
  467. X *
  468. X *    Externally visible functions in the runtime support module
  469. X *    use the naming convention pattern "_db_xx...xx_", thus
  470. X *    they are unlikely to collide with user defined function names.
  471. X *
  472. X *  AUTHOR(S)
  473. X *
  474. X *    Fred Fish        (base code)
  475. X *    (Currently at Motorola Computer Division, Tempe, Az.)
  476. X *    hao!noao!mcdsun!fnf
  477. X *    (602) 438-3614
  478. X *
  479. X *    Binayak Banerjee    (profiling enhancements)
  480. X *    seismo!bpa!sjuvax!bbanerje
  481. X */
  482. X
  483. X
  484. #include <stdio.h>
  485. #ifdef amiga
  486. #define AMIGA
  487. #endif
  488. X
  489. #ifdef AMIGA
  490. #define HZ (50)            /* Probably in some header somewhere */
  491. #endif
  492. X
  493. /*
  494. X *    Manifest constants that should not require any changes.
  495. X */
  496. X
  497. #define FALSE        0    /* Boolean FALSE */
  498. #define TRUE        1    /* Boolean TRUE */
  499. #define EOS        '\000'    /* End Of String marker */
  500. X
  501. /*
  502. X *    Manifest constants which may be "tuned" if desired.
  503. X */
  504. X
  505. #define PRINTBUF    1024    /* Print buffer size */
  506. #define INDENT        4    /* Indentation per trace level */
  507. #define MAXDEPTH    200    /* Maximum trace depth default */
  508. X
  509. /*
  510. X *    The following flags are used to determine which
  511. X *    capabilities the user has enabled with the state
  512. X *    push macro.
  513. X */
  514. X
  515. #define TRACE_ON    000001    /* Trace enabled */
  516. #define DEBUG_ON    000002    /* Debug enabled */
  517. #define FILE_ON     000004    /* File name print enabled */
  518. #define LINE_ON        000010    /* Line number print enabled */
  519. #define DEPTH_ON    000020    /* Function nest level print enabled */
  520. #define PROCESS_ON    000040    /* Process name print enabled */
  521. #define NUMBER_ON    000100    /* Number each line of output */
  522. #define PROFILE_ON    000200    /* Print out profiling code */
  523. X
  524. #define TRACING (stack -> flags & TRACE_ON)
  525. #define DEBUGGING (stack -> flags & DEBUG_ON)
  526. #define PROFILING (stack -> flags & PROFILE_ON)
  527. #define STREQ(a,b) (strcmp(a,b) == 0)
  528. X
  529. /*
  530. X *    Typedefs to make things more obvious.
  531. X */
  532. X
  533. #define VOID void        /* Can't use typedef for most compilers */
  534. typedef int BOOLEAN;
  535. X
  536. /*
  537. X *    Make it easy to change storage classes if necessary.
  538. X */
  539. X
  540. #define LOCAL static        /* Names not needed by outside world */
  541. #define IMPORT extern        /* Names defined externally */
  542. #define EXPORT            /* Allocated here, available globally */
  543. #define AUTO auto        /* Names to be allocated on stack */
  544. #define REGISTER register    /* Names to be placed in registers */
  545. X
  546. /*
  547. X *    The following define is for the variable arguments kluge, see
  548. X *    the comments in _db_doprnt_().
  549. X *
  550. X *    Also note that the longer this list, the less prone to failing
  551. X *    on long argument lists, but the more stuff that must be moved
  552. X *    around for each call to the runtime support routines.  The
  553. X *    length may really be critical if the machine convention is
  554. X *    to pass arguments in registers.
  555. X *
  556. X *    Note that the default define allows up to 16 integral arguments,
  557. X *    or 8 floating point arguments (doubles), on most machines.
  558. X *
  559. X *    Someday this may be replaced with true varargs support, when
  560. X *    ANSI C has had time to take root.
  561. X */
  562. X
  563. #define ARGLIST a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15
  564. X
  565. /*
  566. X * The default file for profiling.  Could also add another flag
  567. X * (G?) which allowed the user to specify this.
  568. X */
  569. X
  570. #define PROF_FILE    "dbugmon.out"
  571. X
  572. /*
  573. X *    Variables which are available externally but should only
  574. X *    be accessed via the macro package facilities.
  575. X */
  576. X
  577. EXPORT FILE *_db_fp_ = stderr;        /* Output stream, default stderr */
  578. EXPORT FILE *_db_pfp_ = (FILE *)0;    /* Profile stream, 'dbugmon.out' */
  579. EXPORT char *_db_process_ = "dbug";    /* Pointer to process name; argv[0] */
  580. EXPORT BOOLEAN _db_on_ = FALSE;        /* TRUE if debugging currently on */
  581. EXPORT BOOLEAN _db_pon_ = FALSE;    /* TRUE if debugging currently on */
  582. X
  583. /*
  584. X *    Externally supplied functions.
  585. X */
  586. X
  587. #ifdef unix            /* Only needed for unix */
  588. IMPORT VOID perror ();        /* Print system/library error */
  589. IMPORT int chown ();        /* Change owner of a file */
  590. IMPORT int getgid ();        /* Get real group id */
  591. IMPORT int getuid ();        /* Get real user id */
  592. IMPORT int access ();        /* Test file for access */
  593. #else
  594. #if !(AMIGA || LATTICE || __TURBOC__)
  595. LOCAL VOID perror ();        /* Fake system/library error print routine */
  596. #endif
  597. #endif
  598. X
  599. # if BSD4_3 || sun
  600. IMPORT int getrusage ();
  601. #endif
  602. X
  603. IMPORT int atoi ();        /* Convert ascii to integer */
  604. IMPORT VOID exit ();        /* Terminate execution */
  605. IMPORT int fclose ();        /* Close a stream */
  606. IMPORT FILE *fopen ();        /* Open a stream */
  607. #if !defined(__BORLANDC__)
  608. IMPORT int fprintf ();        /* Formatted print on file */
  609. #endif
  610. IMPORT VOID free ();
  611. IMPORT char *malloc ();        /* Allocate memory */
  612. IMPORT int strcmp ();        /* Compare strings */
  613. IMPORT char *strcpy ();        /* Copy strings around */
  614. IMPORT int strlen ();        /* Find length of string */
  615. X
  616. #ifndef fflush            /* This is sometimes a macro */
  617. IMPORT int fflush ();        /* Flush output for stream */
  618. #endif
  619. X
  620. X
  621. /*
  622. X *    The user may specify a list of functions to trace or 
  623. X *    debug.  These lists are kept in a linear linked list,
  624. X *    a very simple implementation.
  625. X */
  626. X
  627. struct link {
  628. X    char *string;        /* Pointer to link's contents */
  629. X    struct link *next_link;    /* Pointer to the next link */
  630. };
  631. X
  632. X
  633. /*
  634. X *    Debugging states can be pushed or popped off of a
  635. X *    stack which is implemented as a linked list.  Note
  636. X *    that the head of the list is the current state and the
  637. X *    stack is pushed by adding a new state to the head of the
  638. X *    list or popped by removing the first link.
  639. X */
  640. X
  641. struct state {
  642. X    int flags;                /* Current state flags */
  643. X    int maxdepth;            /* Current maximum trace depth */
  644. X    unsigned int delay;            /* Delay after each output line */
  645. X    int level;                /* Current function nesting level */
  646. X    FILE *out_file;            /* Current output stream */
  647. X    FILE *prof_file;            /* Current profiling stream */
  648. X    struct link *functions;        /* List of functions */
  649. X    struct link *p_functions;        /* List of profiled functions */
  650. X    struct link *keywords;        /* List of debug keywords */
  651. X    struct link *processes;        /* List of process names */
  652. X    struct state *next_state;        /* Next state in the list */
  653. };
  654. X
  655. LOCAL struct state *stack = NULL;    /* Linked list of stacked states */
  656. X
  657. /*
  658. X *    Local variables not seen by user.
  659. X */
  660. X
  661. LOCAL int lineno = 0;        /* Current debugger output line number */
  662. LOCAL char *func = "?func";    /* Name of current user function */
  663. LOCAL char *file = "?file";    /* Name of current user file */
  664. LOCAL BOOLEAN init_done = FALSE;/* Set to TRUE when initialization done */
  665. X
  666. /*#if unix || AMIGA || M_I86*/
  667. LOCAL int jmplevel;        /* Remember nesting level at setjmp () */
  668. LOCAL char *jmpfunc;        /* Remember current function for setjmp */
  669. LOCAL char *jmpfile;        /* Remember current file for setjmp */
  670. /*#endif*/
  671. X
  672. LOCAL struct link *ListParse ();/* Parse a debug command string */
  673. LOCAL char *StrDup ();        /* Make a fresh copy of a string */
  674. LOCAL VOID OpenFile ();        /* Open debug output stream */
  675. LOCAL VOID OpenProfile ();    /* Open profile output stream */
  676. LOCAL VOID CloseFile ();    /* Close debug output stream */
  677. LOCAL VOID PushState ();    /* Push current debug state */
  678. LOCAL VOID ChangeOwner ();    /* Change file owner and group */
  679. LOCAL BOOLEAN DoTrace ();    /* Test for tracing enabled */
  680. LOCAL BOOLEAN Writable ();    /* Test to see if file is writable */
  681. LOCAL unsigned long Clock ();    /* Return current user time (ms) */
  682. LOCAL char *DbugMalloc ();    /* Allocate memory for runtime support */
  683. LOCAL char *BaseName ();    /* Remove leading pathname components */
  684. LOCAL VOID DoPrefix ();        /* Print debugger line prefix */
  685. LOCAL VOID FreeList ();        /* Free memory from linked list */
  686. LOCAL VOID Indent ();        /* Indent line to specified indent */
  687. X
  688. X                /* Supplied in Sys V runtime environ */
  689. LOCAL char *strtok ();        /* Break string into tokens */
  690. LOCAL char *strrchr ();        /* Find last occurance of char */
  691. X
  692. /*
  693. X *    The following local variables are used to hold the state information
  694. X *    between the call to _db_pargs_() and _db_doprnt_(), during
  695. X *    expansion of the DBUG_PRINT macro.  This is the only macro
  696. X *    that currently uses these variables.  The DBUG_PRINT macro
  697. X *    and the new _db_doprnt_() routine replace the older DBUG_N macros
  698. X *    and their corresponding runtime support routine _db_printf_().
  699. X *
  700. X *    These variables are currently used only by _db_pargs_() and
  701. X *    _db_doprnt_().
  702. X */
  703. X
  704. LOCAL int u_line = 0;        /* User source code line number */
  705. LOCAL char *u_keyword = "?";    /* Keyword for current macro */
  706. X
  707. /*
  708. X *    Miscellaneous printf format strings.
  709. X */
  710. #define ERR_MISSING_RETURN "%s: missing DBUG_RETURN or DBUG_VOID_RETURN macro in function \"%s\"\n"
  711. #define ERR_OPEN "%s: can't open debug output stream \"%s\": "
  712. #define ERR_CLOSE "%s: can't close debug file: "
  713. #define ERR_ABORT "%s: debugger aborting because %s\n"
  714. #define ERR_CHOWN "%s: can't change owner/group of \"%s\": "
  715. #define ERR_PRINTF "%s: obsolete object file for '%s', please recompile!\n"
  716. X
  717. /*
  718. X *    Macros and defines for testing file accessibility under UNIX.
  719. X */
  720. X
  721. #ifdef unix
  722. #  define A_EXISTS    00        /* Test for file existance */
  723. #  define A_EXECUTE    01        /* Test for execute permission */
  724. #  define A_WRITE    02        /* Test for write access */
  725. #  define A_READ    03        /* Test for read access */
  726. #  define EXISTS(pathname) (access (pathname, A_EXISTS) == 0)
  727. #  define WRITABLE(pathname) (access (pathname, A_WRITE) == 0)
  728. #else
  729. #  define EXISTS(pathname) (FALSE)    /* Assume no existance */
  730. #endif
  731. X
  732. /*
  733. X *    Translate some calls among different systems.
  734. X */
  735. X
  736. #ifdef unix
  737. # define XDelay sleep
  738. IMPORT unsigned int sleep ();    /* Pause for given number of seconds */
  739. #endif
  740. X
  741. #ifdef AMIGA
  742. IMPORT int XDelay ();        /* Pause for given number of ticks */
  743. #endif
  744. X
  745. X
  746. /*
  747. X *  FUNCTION
  748. X *
  749. X *    _db_push_    push current debugger state and set up new one
  750. X *
  751. X *  SYNOPSIS
  752. X *
  753. X *    VOID _db_push_ (control)
  754. X *    char *control;
  755. X *
  756. X *  DESCRIPTION
  757. X *
  758. X *    Given pointer to a debug control string in "control", pushes
  759. X *    the current debug state, parses the control string, and sets
  760. X *    up a new debug state.
  761. X *
  762. X *    The only attribute of the new state inherited from the previous
  763. X *    state is the current function nesting level.  This can be
  764. X *    overridden by using the "r" flag in the control string.
  765. X *
  766. X *    The debug control string is a sequence of colon separated fields
  767. X *    as follows:
  768. X *
  769. X *        <field_1>:<field_2>:...:<field_N>
  770. X *
  771. X *    Each field consists of a mandatory flag character followed by
  772. X *    an optional "," and comma separated list of modifiers:
  773. X *
  774. X *        flag[,modifier,modifier,...,modifier]
  775. X *
  776. X *    The currently recognized flag characters are:
  777. X *
  778. X *        d    Enable output from DBUG_<N> macros for
  779. X *            for the current state.  May be followed
  780. X *            by a list of keywords which selects output
  781. X *            only for the DBUG macros with that keyword.
  782. X *            A null list of keywords implies output for
  783. X *            all macros.
  784. X *
  785. X *        D    Delay after each debugger output line.
  786. X *            The argument is the number of tenths of seconds
  787. X *            to delay, subject to machine capabilities.
  788. X *            I.E.  -#D,20 is delay two seconds.
  789. X *
  790. X *        f    Limit debugging and/or tracing, and profiling to the
  791. X *            list of named functions.  Note that a null list will
  792. X *            disable all functions.  The appropriate "d" or "t"
  793. X *            flags must still be given, this flag only limits their
  794. X *            actions if they are enabled.
  795. X *
  796. X *        F    Identify the source file name for each
  797. X *            line of debug or trace output.
  798. X *
  799. X *        g    Enable profiling.  Create a file called 'dbugmon.out'
  800. X *            containing information that can be used to profile
  801. X *            the program.  May be followed by a list of keywords
  802. X *            that select profiling only for the functions in that
  803. X *            list.  A null list implies that all functions are
  804. X *            considered.
  805. X *
  806. X *        L    Identify the source file line number for
  807. X *            each line of debug or trace output.
  808. X *
  809. X *        n    Print the current function nesting depth for
  810. X *            each line of debug or trace output.
  811. X *    
  812. X *        N    Number each line of dbug output.
  813. X *
  814. X *        p    Limit debugger actions to specified processes.
  815. X *            A process must be identified with the
  816. X *            DBUG_PROCESS macro and match one in the list
  817. X *            for debugger actions to occur.
  818. X *
  819. X *        P    Print the current process name for each
  820. X *            line of debug or trace output.
  821. X *
  822. X *        r    When pushing a new state, do not inherit
  823. X *            the previous state's function nesting level.
  824. X *            Useful when the output is to start at the
  825. X *            left margin.
  826. X *
  827. X *        t    Enable function call/exit trace lines.
  828. X *            May be followed by a list (containing only
  829. X *            one modifier) giving a numeric maximum
  830. X *            trace level, beyond which no output will
  831. X *            occur for either debugging or tracing
  832. X *            macros.  The default is a compile time
  833. X *            option.
  834. X *
  835. X *    Some examples of debug control strings which might appear
  836. X *    on a shell command line (the "-#" is typically used to
  837. X *    introduce a control string to an application program) are:
  838. X *
  839. X *        -#d:t
  840. X *        -#d:f,main,subr1:F:L:t,20
  841. X *        -#d,input,output,files:n
  842. X *
  843. X *    For convenience, any leading "-#" is stripped off.
  844. X *
  845. X */
  846. X
  847. X
  848. VOID _db_push_ (control)
  849. char *control;
  850. {
  851. X    REGISTER char *scan;
  852. X    REGISTER struct link *temp;
  853. X
  854. X    if (control && *control == '-') {
  855. X    if (*++control == '#') {
  856. X        control++;
  857. X    }    
  858. X    }
  859. X    control = StrDup (control);
  860. X    PushState ();
  861. X    scan = strtok (control, ":");
  862. X    for (; scan != NULL; scan = strtok ((char *)NULL, ":")) {
  863. X    switch (*scan++) {
  864. X        case 'd': 
  865. X        _db_on_ = TRUE;
  866. X        stack -> flags |= DEBUG_ON;
  867. X        if (*scan++ == ',') {
  868. X            stack -> keywords = ListParse (scan);
  869. X        }
  870. X            break;
  871. X        case 'D': 
  872. X        stack -> delay = 0;
  873. X        if (*scan++ == ',') {
  874. X            temp = ListParse (scan);
  875. X            stack -> delay = DelayArg (atoi (temp -> string));
  876. X            FreeList (temp);
  877. X        }
  878. X        break;
  879. X        case 'f': 
  880. X        if (*scan++ == ',') {
  881. X            stack -> functions = ListParse (scan);
  882. X        }
  883. X        break;
  884. X        case 'F': 
  885. X        stack -> flags |= FILE_ON;
  886. X        break;
  887. X        case 'g': 
  888. X        _db_pon_ = TRUE;
  889. X        OpenProfile(PROF_FILE);
  890. X        stack -> flags |= PROFILE_ON;
  891. X        if (*scan++ == ',') {
  892. X            stack -> p_functions = ListParse (scan);
  893. X        }
  894. X        break;
  895. X        case 'L': 
  896. X        stack -> flags |= LINE_ON;
  897. X        break;
  898. X        case 'n': 
  899. X        stack -> flags |= DEPTH_ON;
  900. X        break;
  901. X        case 'N':
  902. X        stack -> flags |= NUMBER_ON;
  903. X        break;
  904. X        case 'o': 
  905. X        if (*scan++ == ',') {
  906. X            temp = ListParse (scan);
  907. X            OpenFile (temp -> string);
  908. X            FreeList (temp);
  909. X        } else {
  910. X            OpenFile ("-");
  911. X        }
  912. X        break;
  913. X        case 'p':
  914. X        if (*scan++ == ',') {
  915. X            stack -> processes = ListParse (scan);
  916. X        }
  917. X        break;
  918. X        case 'P': 
  919. X        stack -> flags |= PROCESS_ON;
  920. X        break;
  921. X        case 'r': 
  922. X        stack -> level = 0;
  923. X        break;
  924. X        case 't': 
  925. X        stack -> flags |= TRACE_ON;
  926. X        if (*scan++ == ',') {
  927. X            temp = ListParse (scan);
  928. X            stack -> maxdepth = atoi (temp -> string);
  929. X            FreeList (temp);
  930. X        }
  931. X        break;
  932. X    }
  933. X    }
  934. X    free (control);
  935. }
  936. X
  937. X
  938. X
  939. /*
  940. X *  FUNCTION
  941. X *
  942. X *    _db_pop_    pop the debug stack
  943. X *
  944. X *  DESCRIPTION
  945. X *
  946. X *    Pops the debug stack, returning the debug state to its
  947. X *    condition prior to the most recent _db_push_ invocation.
  948. X *    Note that the pop will fail if it would remove the last
  949. X *    valid state from the stack.  This prevents user errors
  950. X *    in the push/pop sequence from screwing up the debugger.
  951. X *    Maybe there should be some kind of warning printed if the
  952. X *    user tries to pop too many states.
  953. X *
  954. X */
  955. X
  956. VOID _db_pop_ ()
  957. {
  958. X    REGISTER struct state *discard;
  959. X
  960. X    discard = stack;
  961. X    if (discard != NULL && discard -> next_state != NULL) {
  962. X    stack = discard -> next_state;
  963. X    _db_fp_ = stack -> out_file;
  964. X    _db_pfp_ = stack -> prof_file;
  965. X    if (discard -> keywords != NULL) {
  966. X        FreeList (discard -> keywords);
  967. X    }
  968. X    if (discard -> functions != NULL) {
  969. X        FreeList (discard -> functions);
  970. X    }
  971. X    if (discard -> processes != NULL) {
  972. X        FreeList (discard -> processes);
  973. X    }
  974. X    if (discard -> p_functions != NULL) {
  975. X        FreeList (discard -> p_functions);
  976. X    }
  977. X    CloseFile (discard -> out_file);
  978. X    CloseFile (discard -> prof_file);
  979. X    free ((char *) discard);
  980. X    }
  981. }
  982. X
  983. X
  984. /*
  985. X *  FUNCTION
  986. X *
  987. X *    _db_enter_    process entry point to user function
  988. X *
  989. X *  SYNOPSIS
  990. X *
  991. X *    VOID _db_enter_ (_func_, _file_, _line_, _sfunc_, _sfile_, _slevel_)
  992. X *    char *_func_;        points to current function name
  993. X *    char *_file_;        points to current file name
  994. X *    int _line_;        called from source line number
  995. X *    char **_sfunc_;        save previous _func_
  996. X *    char **_sfile_;        save previous _file_
  997. X *    int *_slevel_;        save previous nesting level
  998. X *
  999. X *  DESCRIPTION
  1000. X *
  1001. X *    Called at the beginning of each user function to tell
  1002. X *    the debugger that a new function has been entered.
  1003. X *    Note that the pointers to the previous user function
  1004. X *    name and previous user file name are stored on the
  1005. X *    caller's stack (this is why the ENTER macro must be
  1006. X *    the first "executable" code in a function, since it
  1007. X *    allocates these storage locations).  The previous nesting
  1008. X *    level is also stored on the callers stack for internal
  1009. X *    self consistency checks.
  1010. X *
  1011. X *    Also prints a trace line if tracing is enabled and
  1012. X *    increments the current function nesting depth.
  1013. X *
  1014. X *    Note that this mechanism allows the debugger to know
  1015. X *    what the current user function is at all times, without
  1016. X *    maintaining an internal stack for the function names.
  1017. X *
  1018. X */
  1019. X
  1020. VOID _db_enter_ (_func_, _file_, _line_, _sfunc_, _sfile_, _slevel_)
  1021. char *_func_;
  1022. char *_file_;
  1023. int _line_;
  1024. char **_sfunc_;
  1025. char **_sfile_;
  1026. int *_slevel_;
  1027. {
  1028. X    if (!init_done) {
  1029. X    _db_push_ ("");
  1030. X    }
  1031. X    *_sfunc_ = func;
  1032. X    *_sfile_ = file;
  1033. X    func = _func_;
  1034. X    file = BaseName (_file_);
  1035. X    stack -> level++;
  1036. X    *_slevel_ = stack -> level;
  1037. X    if (DoProfile ()) {
  1038. X    (VOID) fprintf (_db_pfp_, "%s\tE\t%ld\n",func, Clock());
  1039. X    (VOID) fflush (_db_pfp_);
  1040. X    }
  1041. X    if (DoTrace ()) {
  1042. X    DoPrefix (_line_);
  1043. X    Indent (stack -> level);
  1044. X    (VOID) fprintf (_db_fp_, ">%s\n", func);
  1045. X    (VOID) fflush (_db_fp_);
  1046. X    (VOID) XDelay (stack -> delay);
  1047. X    }
  1048. }
  1049. X
  1050. X
  1051. /*
  1052. X *  FUNCTION
  1053. X *
  1054. X *    _db_return_    process exit from user function
  1055. X *
  1056. X *  SYNOPSIS
  1057. X *
  1058. X *    VOID _db_return_ (_line_, _sfunc_, _sfile_, _slevel_)
  1059. X *    int _line_;        current source line number
  1060. X *    char **_sfunc_;        where previous _func_ is to be retrieved
  1061. X *    char **_sfile_;        where previous _file_ is to be retrieved
  1062. X *    int *_slevel_;        where previous level was stashed
  1063. X *
  1064. X *  DESCRIPTION
  1065. X *
  1066. X *    Called just before user function executes an explicit or implicit
  1067. X *    return.  Prints a trace line if trace is enabled, decrements
  1068. X *    the current nesting level, and restores the current function and
  1069. X *    file names from the defunct function's stack.
  1070. X *
  1071. X */
  1072. X
  1073. VOID _db_return_ (_line_, _sfunc_, _sfile_, _slevel_)
  1074. int _line_;
  1075. char **_sfunc_;
  1076. char **_sfile_;
  1077. int *_slevel_;
  1078. {
  1079. X    if (!init_done) {
  1080. X    _db_push_ ("");
  1081. X    }
  1082. X    if (stack -> level != *_slevel_ && (TRACING || DEBUGGING || PROFILING)) {
  1083. X    (VOID) fprintf (_db_fp_, ERR_MISSING_RETURN, _db_process_, func);
  1084. X        (VOID) XDelay (stack -> delay);
  1085. X    } else if (DoProfile ()) {
  1086. X    (VOID) fprintf (_db_pfp_, "%s\tX\t%ld\n", func, Clock());
  1087. X        (VOID) XDelay (stack -> delay);
  1088. X    } else if (DoTrace ()) {
  1089. X    DoPrefix (_line_);
  1090. X    Indent (stack -> level);
  1091. X    (VOID) fprintf (_db_fp_, "<%s\n", func);
  1092. X        (VOID) XDelay (stack -> delay);
  1093. X    }
  1094. X    (VOID) fflush (_db_fp_);
  1095. X    stack -> level = *_slevel_ - 1;
  1096. X    func = *_sfunc_;
  1097. X    file = *_sfile_;
  1098. }
  1099. X
  1100. X
  1101. /*
  1102. X *  FUNCTION
  1103. X *
  1104. X *    _db_pargs_    log arguments for subsequent use by _db_doprnt_()
  1105. X *
  1106. X *  SYNOPSIS
  1107. X *
  1108. X *    VOID _db_pargs_ (_line_, keyword)
  1109. X *    int _line_;
  1110. X *    char *keyword;
  1111. X *
  1112. X *  DESCRIPTION
  1113. X *
  1114. X *    The new universal printing macro DBUG_PRINT, which replaces
  1115. X *    all forms of the DBUG_N macros, needs two calls to runtime
  1116. X *    support routines.  The first, this function, remembers arguments
  1117. X *    that are used by the subsequent call to _db_doprnt_().
  1118. *
  1119. X */
  1120. X
  1121. VOID _db_pargs_ (_line_, keyword)
  1122. int _line_;
  1123. char *keyword;
  1124. {
  1125. X    u_line = _line_;
  1126. X    u_keyword = keyword;
  1127. }
  1128. X
  1129. X
  1130. /*
  1131. X *  FUNCTION
  1132. X *
  1133. X *    _db_doprnt_    handle print of debug lines
  1134. X *
  1135. X *  SYNOPSIS
  1136. X *
  1137. X *    VOID _db_doprnt_ (format, ARGLIST)
  1138. X *    char *format;
  1139. X *    long ARGLIST;
  1140. X *
  1141. X *  DESCRIPTION
  1142. X *
  1143. X *    When invoked via one of the DBUG macros, tests the current keyword
  1144. X *    set by calling _db_pargs_() to see if that macro has been selected
  1145. X *    for processing via the debugger control string, and if so, handles
  1146. X *    printing of the arguments via the format string.  The line number
  1147. X *    of the DBUG macro in the source is found in u_line.
  1148. X *
  1149. X *    Note that the format string SHOULD NOT include a terminating
  1150. X *    newline, this is supplied automatically.
  1151. X *
  1152. X *  NOTES
  1153. X *
  1154. X *    This runtime support routine replaces the older _db_printf_()
  1155. X *    routine which is temporarily kept around for compatibility.
  1156. X *
  1157. X *    The rather ugly argument declaration is to handle some
  1158. X *    magic with respect to the number of arguments passed
  1159. X *    via the DBUG macros.  The current maximum is 3 arguments
  1160. X *    (not including the keyword and format strings).
  1161. X *
  1162. X *    The new <varargs.h> facility is not yet common enough to
  1163. X *    convert to it quite yet...
  1164. X *
  1165. X */
  1166. X
  1167. /*VARARGS1*/
  1168. VOID _db_doprnt_ (format, ARGLIST)
  1169. char *format;
  1170. long ARGLIST;
  1171. {
  1172. X    if (_db_keyword_ (u_keyword)) {
  1173. X    DoPrefix (u_line);
  1174. X    if (TRACING) {
  1175. X        Indent (stack -> level + 1);
  1176. X    } else {
  1177. X        (VOID) fprintf (_db_fp_, "%s: ", func);
  1178. X    }
  1179. X    (VOID) fprintf (_db_fp_, "%s: ", u_keyword);
  1180. X    (VOID) fprintf (_db_fp_, format, ARGLIST);
  1181. X    (VOID) fprintf (_db_fp_, "\n");
  1182. X    (VOID) fflush (_db_fp_);
  1183. X    (VOID) XDelay (stack -> delay);
  1184. X    }
  1185. }
  1186. X
  1187. /*
  1188. X *    The following routine is kept around temporarily for compatibility
  1189. X *    with older objects that were compiled with the DBUG_N macro form
  1190. X *    of the print routine.  It will print a warning message on first
  1191. X *    usage.  It will go away in subsequent releases...
  1192. X */
  1193. X
  1194. /*VARARGS3*/
  1195. VOID _db_printf_ (_line_, keyword, format, ARGLIST)
  1196. int _line_;
  1197. char *keyword,  *format;
  1198. long ARGLIST;
  1199. {
  1200. X    static BOOLEAN firsttime = TRUE;
  1201. X
  1202. X    if (firsttime) {
  1203. X    (VOID) fprintf (stderr, ERR_PRINTF, _db_process_, file);
  1204. X    firsttime = FALSE;
  1205. X    }
  1206. X    _db_pargs_ (_line_, keyword);
  1207. X    _db_doprnt_ (format, ARGLIST);
  1208. }
  1209. X
  1210. X
  1211. /*
  1212. X *  FUNCTION
  1213. X *
  1214. X *    ListParse    parse list of modifiers in debug control string
  1215. X *
  1216. X *  SYNOPSIS
  1217. X *
  1218. X *    LOCAL struct link *ListParse (ctlp)
  1219. X *    char *ctlp;
  1220. X *
  1221. X *  DESCRIPTION
  1222. X *
  1223. X *    Given pointer to a comma separated list of strings in "cltp",
  1224. X *    parses the list, building a list and returning a pointer to it.
  1225. X *    The original comma separated list is destroyed in the process of
  1226. X *    building the linked list, thus it had better be a duplicate
  1227. X *    if it is important.
  1228. X *
  1229. X *    Note that since each link is added at the head of the list,
  1230. X *    the final list will be in "reverse order", which is not
  1231. X *    significant for our usage here.
  1232. X *
  1233. X */
  1234. X
  1235. LOCAL struct link *ListParse (ctlp)
  1236. char *ctlp;
  1237. {
  1238. X    REGISTER char *start;
  1239. X    REGISTER struct link *new;
  1240. X    REGISTER struct link *head;
  1241. X
  1242. X    head = NULL;
  1243. X    while (*ctlp != EOS) {
  1244. X    start = ctlp;
  1245. X    while (*ctlp != EOS && *ctlp != ',') {
  1246. X        ctlp++;
  1247. X    }
  1248. X    if (*ctlp == ',') {
  1249. X        *ctlp++ = EOS;
  1250. X    }
  1251. X    new = (struct link *) DbugMalloc (sizeof (struct link));
  1252. X    new -> string = StrDup (start);
  1253. X    new -> next_link = head;
  1254. X    head = new;
  1255. X    }
  1256. X    return (head);
  1257. }
  1258. X
  1259. X
  1260. /*
  1261. X *  FUNCTION
  1262. X *
  1263. X *    InList    test a given string for member of a given list
  1264. X *
  1265. X *  SYNOPSIS
  1266. X *
  1267. X *    LOCAL BOOLEAN InList (linkp, cp)
  1268. X *    struct link *linkp;
  1269. X *    char *cp;
  1270. X *
  1271. X *  DESCRIPTION
  1272. X *
  1273. X *    Tests the string pointed to by "cp" to determine if it is in
  1274. X *    the list pointed to by "linkp".  Linkp points to the first
  1275. X *    link in the list.  If linkp is NULL then the string is treated
  1276. X *    as if it is in the list (I.E all strings are in the null list).
  1277. X *    This may seem rather strange at first but leads to the desired
  1278. X *    operation if no list is given.  The net effect is that all
  1279. X *    strings will be accepted when there is no list, and when there
  1280. X *    is a list, only those strings in the list will be accepted.
  1281. X *
  1282. X */
  1283. X
  1284. LOCAL BOOLEAN InList (linkp, cp)
  1285. struct link *linkp;
  1286. char *cp;
  1287. {
  1288. X    REGISTER struct link *scan;
  1289. X    REGISTER BOOLEAN accept;
  1290. X
  1291. X    if (linkp == NULL) {
  1292. X    accept = TRUE;
  1293. X    } else {
  1294. X    accept = FALSE;
  1295. X    for (scan = linkp; scan != NULL; scan = scan -> next_link) {
  1296. X        if (STREQ (scan -> string, cp)) {
  1297. X        accept = TRUE;
  1298. X        break;
  1299. X        }
  1300. X    }
  1301. X    }
  1302. X    return (accept);
  1303. }
  1304. X
  1305. X
  1306. /*
  1307. X *  FUNCTION
  1308. X *
  1309. X *    PushState    push current state onto stack and set up new one
  1310. X *
  1311. X *  SYNOPSIS
  1312. X *
  1313. X *    LOCAL VOID PushState ()
  1314. X *
  1315. X *  DESCRIPTION
  1316. X *
  1317. X *    Pushes the current state on the state stack, and initializes
  1318. X *    a new state.  The only parameter inherited from the previous
  1319. X *    state is the function nesting level.  This action can be
  1320. X *    inhibited if desired, via the "r" flag.
  1321. X *
  1322. X *    The state stack is a linked list of states, with the new
  1323. X *    state added at the head.  This allows the stack to grow
  1324. X *    to the limits of memory if necessary.
  1325. X *
  1326. X */
  1327. X
  1328. LOCAL VOID PushState ()
  1329. {
  1330. X    REGISTER struct state *new;
  1331. X
  1332. X    new = (struct state *) DbugMalloc (sizeof (struct state));
  1333. X    new -> flags = 0;
  1334. X    new -> delay = 0;
  1335. X    new -> maxdepth = MAXDEPTH;
  1336. X    if (stack != NULL) {
  1337. X    new -> level = stack -> level;
  1338. X    } else {
  1339. X    new -> level = 0;
  1340. X    }
  1341. X    new -> out_file = stderr;
  1342. X    new -> functions = NULL;
  1343. X    new -> p_functions = NULL;
  1344. X    new -> keywords = NULL;
  1345. X    new -> processes = NULL;
  1346. X    new -> next_state = stack;
  1347. X    stack = new;
  1348. X    init_done = TRUE;
  1349. }
  1350. X
  1351. X
  1352. /*
  1353. X *  FUNCTION
  1354. X *
  1355. X *    DoTrace    check to see if tracing is current enabled
  1356. X *
  1357. X *  SYNOPSIS
  1358. X *
  1359. X *    LOCAL BOOLEAN DoTrace ()
  1360. X *
  1361. X *  DESCRIPTION
  1362. X *
  1363. X *    Checks to see if tracing is enabled based on whether the
  1364. X *    user has specified tracing, the maximum trace depth has
  1365. X *    not yet been reached, the current function is selected,
  1366. X *    and the current process is selected.  Returns TRUE if
  1367. X *    tracing is enabled, FALSE otherwise.
  1368. X *
  1369. X */
  1370. X
  1371. LOCAL BOOLEAN DoTrace ()
  1372. {
  1373. X    REGISTER BOOLEAN trace;
  1374. X
  1375. X    trace = FALSE;
  1376. X    if (TRACING) {
  1377. X    if (stack -> level <= stack -> maxdepth) {
  1378. X        if (InList (stack -> functions, func)) {
  1379. X        if (InList (stack -> processes, _db_process_)) {
  1380. X            trace = TRUE;
  1381. X        }
  1382. X        }
  1383. X    }
  1384. X    }
  1385. X    return (trace);
  1386. }
  1387. X
  1388. X
  1389. /*
  1390. X *  FUNCTION
  1391. X *
  1392. X *    DoProfile    check to see if profiling is current enabled
  1393. X *
  1394. X *  SYNOPSIS
  1395. X *
  1396. X *    LOCAL BOOLEAN DoProfile ()
  1397. X *
  1398. X *  DESCRIPTION
  1399. X *
  1400. X *    Checks to see if profiling is enabled based on whether the
  1401. X *    user has specified profiling, the maximum trace depth has
  1402. X *    not yet been reached, the current function is selected,
  1403. X *    and the current process is selected.  Returns TRUE if
  1404. SHAR_EOF
  1405. true || echo 'restore of dmake/dbug/dbug/dbug.c failed'
  1406. fi
  1407. echo 'End of part 2, continue with part 3'
  1408. echo 3 > _shar_seq_.tmp
  1409. exit 0
  1410. exit 0 # Just in case...
  1411.